package com.dongdongshop.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.dongdongshop.constant.SeckillConstant;
import com.dongdongshop.mapper.TbSeckillGoodsMapper;
import com.dongdongshop.pojo.TbSeckillGoods;
import com.dongdongshop.pojo.TbSeckillGoodsExample;
import com.dongdongshop.pojo.TbUser;
import com.dongdongshop.service.SeckillService;
import org.apache.dubbo.config.annotation.DubboService;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

@Service
@DubboService
public class SeckillServiceImpl implements SeckillService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Resource
    private TbSeckillGoodsMapper seckillGoodsMapper;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Override
    public void preHotCache() {
        Date now = new Date();
        TbSeckillGoodsExample example = new TbSeckillGoodsExample();
        TbSeckillGoodsExample.Criteria criteria = example.createCriteria();
        criteria.andStartTimeLessThanOrEqualTo(now);//开始时间小于等于当前时间
        criteria.andEndTimeGreaterThanOrEqualTo(now);//结束时间大于等于当前时间
        List<TbSeckillGoods> seckillGoodsList = seckillGoodsMapper.selectByExample(example);
        //将数据更新到缓存中
        seckillGoodsList.stream().forEach(goods -> {
            redisTemplate.boundHashOps(SeckillConstant.SECKILL_LIST).put(goods.getId(), goods);
            stringRedisTemplate.boundValueOps(SeckillConstant.SECKILL_GOODS_STOCKCOUNT + goods.getId()).set(String.valueOf(goods.getStockCount()));
        });
    }

    @Override
    public List<TbSeckillGoods> seckillList() {
        return redisTemplate.boundHashOps(SeckillConstant.SECKILL_LIST).values();
    }

    @Override
    public TbSeckillGoods selectSeckillById(Long id) {
        return (TbSeckillGoods) redisTemplate.boundHashOps(SeckillConstant.SECKILL_LIST).get(id);
    }

    @Override
    public void createOrder(TbUser user, Long seckillGoodsId) {
        //从缓存中取出秒杀商品
        String stockCount = stringRedisTemplate.boundValueOps(SeckillConstant.SECKILL_GOODS_STOCKCOUNT + seckillGoodsId).get();
        //有可能商品卖完之后删除缓存
        if (stockCount == null) {
            throw new RuntimeException("商品已售罄");
        }
        //判断缓存
        if (Long.valueOf(stockCount) <= 0) {
            throw new RuntimeException("商品已售罄");
        }

        //自减1 并且返回自减后的数据 这些步骤原子性
        Long decrement = stringRedisTemplate.boundValueOps(SeckillConstant.SECKILL_GOODS_STOCKCOUNT + seckillGoodsId).decrement();//减一
        TbSeckillGoods goods = selectSeckillById(seckillGoodsId);
        goods.setStockCount(decrement.intValue());
        redisTemplate.boundHashOps(SeckillConstant.SECKILL_LIST).put(seckillGoodsId,goods);
        //如果卖完最后一个
        if (decrement.longValue() == 0){
            //更新库存
            goods.setStockCount(0);
            seckillGoodsMapper.updateByPrimaryKeySelective(goods);
        }

        JSONObject json = new JSONObject();
        json.put("userName",user.getUsername());
        json.put("seckillGoodsId", seckillGoodsId);
        rocketMQTemplate.convertAndSend(SeckillConstant.SECKILL_GOODS_TOPIC,json.toJSONString());
    }

    @Override
    public Long getOrderId(Long userId) {
        return (Long) redisTemplate.boundValueOps(SeckillConstant.SECKILL_ORDER + userId).get();
    }
}
